Skip to content

docs(babysit-pipeline): correct the backfill guidance, retry the driver's fetch - #10660

Merged
MarkusNeusinger merged 5 commits into
mainfrom
docs/babysit-skill-corrections
Aug 26, 2026
Merged

docs(babysit-pipeline): correct the backfill guidance, retry the driver's fetch#10660
MarkusNeusinger merged 5 commits into
mainfrom
docs/babysit-skill-corrections

Conversation

@MarkusNeusinger

@MarkusNeusinger MarkusNeusinger commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Why

#10628 documented gap backfill while the backfill was still running. Finishing it falsified three of its claims, so this PR corrects them rather than leaving confident wrong guidance in a skill. Running the backfill in two parallel slots also exposed a race in the driver, fixed here.

Scope: prose plus one executable change. SKILL.md and CHANGELOG.md are documentation; run_spec.sh gains a fetch retry (behaviour change, details below).

Corrections

1. Halt-on-cluster counted the wrong thing. The threshold was "≥5 failed Generate: runs in minutes = quota exhausted". Since #10627 restored the full retry budget, a single impossible pair spends three runs on its own auto-retries — so two bad pairs trip a raw count of five while the pipeline is perfectly healthy. That happened during the run: 6 failures at 22:29–22:37, all of them plotnine on two specs, nothing wrong with the pipeline. Now counts distinct (spec, library) pairs.

2. "Static library + interactive/3D spec is the one gap that is usually real" was backwards. Every category-level prediction made during the backfill turned out wrong:

Prediction Outcome
chartjs can't do treemap / sankey chartjs succeeded on network-force-directed, arc-basic, and every JS-block spec
plotnine can't do 3D bar-3d-categorical succeeded; scatter-3d did not
ggplot2 can't do wireframe succeeded on retry
pygal is a lost cause (6 failed labels) succeeded on map-marker-clustered and line-stress-strain

17 of 20 parked pairs generated fine. Exactly three failed under a full budget — plotnine on scatter-3d, contour-3d, line-3d-trajectory, all of which need a spatial projection plotnine does not have, while the "3D" spec representable in 2D went through. The gotcha now says: measure, don't predict.

3. The one-retry rule needed a precondition. The workflow now spends three attempts per campaign by itself, so a pair that comes back missing may already be measured and the manual retry adds nothing. The skill now shows the actual command — gh run list has no per-spec filter, so it filters the output by run title with jq. Three failures minutes apart is a gap, one is a flake. The same check resolves RESULT=TIMEOUT with recent generate failures: 0, which only means the failures aged out of the driver's 25-minute window (seen on line-3d-trajectory, which had in fact failed three times 40 minutes earlier).

New gotcha

Spec IDs harvested from impl:*:failed issue titles must be intersected with the real plots/ directories: 14 of 26 pointed at specs that no longer exist on main, and such a dispatch dies seconds in at Validate specification exists. This is how the rescue list first read as 45 missing implementations when only 20 were real.

Behaviour change: run_spec.sh retries its fetch

Two drivers polling the same checkout collide on the ref lock:

error: cannot lock ref 'refs/remotes/origin/main': is at 6b666c10 but expected c736a848

A lost fetch leaves origin/main stale, so meta_present understates what has landed and the poller reports PARTIAL for libraries that are already merged — a failure that disguises itself as a stalled spec. fetch_main() now retries three times with backoff and, when all three lose, logs the warning with git's own stderr so a ref-lock collision is distinguishable from an auth or network failure.

Verification

  • bash -n on run_spec.sh; the failure path exercised against a bad ref → last error: fatal: couldn't find remote ref …, confirming the message survives to the log.
  • Every number in the corrections traces to a workflow run or label query from the 2026-08-24 backfill; the ledger is in agentic/runs/babysit-2026-08-20/.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01RbZuWNDFy7kjXh9kLfA4dP

…ished run

#10628 was written while the backfill was still running. Finishing it
falsified three of its claims.

- Halt-on-cluster counted raw failed `Generate:` runs. Since #10627 an
  impossible pair spends three runs on its own retries, so two bad pairs
  trip a threshold of five while nothing is wrong — observed exactly that
  (6 failures, 2 pairs, healthy pipeline). Count distinct (spec, library)
  pairs instead.
- "Static library against an interactive or 3D spec is the one gap that
  is usually real" is replaced by its opposite. Every category-level
  prediction the backfill made was wrong: 17 of 20 parked pairs
  generated fine, pygal and chartjs each succeeded on the plot types
  they had been written off for, and bar-3d-categorical succeeded in
  plotnine while scatter-3d did not. Three pairs failed under a full
  budget — plotnine on scatter-3d, contour-3d and line-3d-trajectory,
  all needing a spatial projection plotnine lacks. A gap is real when
  three attempts say so, not when the pairing sounds implausible.
- The one-retry rule needs a precondition now: the workflow already
  spends three attempts per campaign, so check the run list before
  adding a manual one. Three failures minutes apart is a measured gap;
  one is a flake. Same check resolves `RESULT=TIMEOUT` with
  `recent generate failures: 0`, which only means they aged out of the
  driver's 25-minute window.

New gotcha: intersect label-derived spec ids with the real `plots/`
directories. 14 of 26 ids harvested from `impl:*:failed` issue titles
had no spec on main, and such a dispatch dies at "Validate
specification exists".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbZuWNDFy7kjXh9kLfA4dP
Copilot AI lite review requested due to automatic review settings August 25, 2026 00:17
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbZuWNDFy7kjXh9kLfA4dP

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The updated skill text includes a misleading “filtered to the spec” instruction for gh run list that should be clarified to avoid incorrect operator usage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the babysit-pipeline skill documentation to correct gap-backfill guidance based on the completed 2026-08-24 backfill run, and records the correction in CHANGELOG.md.

Changes:

  • Adjusted the “halt-on-cluster” guidance to count distinct (spec, library) pairs rather than raw failed Generate: runs.
  • Replaced capability “prediction” guidance with a “measure, don’t predict” rule and added a gotcha about spec IDs harvested from issue titles not necessarily existing on main.
  • Added a corresponding [Unreleased] changelog entry describing the corrected guidance.
File summaries
File Description
CHANGELOG.md Adds an [Unreleased] entry documenting the corrected gap-backfill guidance.
.claude/skills/babysit-pipeline/SKILL.md Updates the skill’s gap-backfill gotchas and halt/deferral guidance to match observed backfill behavior.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread CHANGELOG.md Outdated
Comment on lines +216 to +217
- **A spec id from an issue title may not exist.** `impl:*:failed`
labels outlive their specs: of 26 spec ids harvested that way, 14

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied — "spec IDs". Matches the repo's existing usage (3 occurrences of "spec IDs" against the 1 I introduced) and the Google style guide this repo follows.

Comment on lines +170 to +172
manual retry adds nothing. `gh run list --workflow=impl-generate.yml`
filtered to the spec tells you which case you are in — three
`Generate: <lib> for <spec>` failures minutes apart is a measured

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the sentence implied a flag that does not exist. It now shows the actual command, filtering the output by run title:

gh run list --workflow=impl-generate.yml --limit 40 \
  --json conclusion,createdAt,displayTitle \
  --jq '.[] | select(.displayTitle | test("<spec>")) | "\(.createdAt) \(.conclusion) \(.displayTitle)"'

…vers

Two drivers polling the same checkout collide on
.git/refs/remotes/origin/main:

  error: cannot lock ref 'refs/remotes/origin/main': is at 6b666c1 but
  expected c736a84

A lost fetch leaves origin/main stale, so meta_present understates what
has landed and the poller reports PARTIAL for libraries that are already
merged. Retry three times with backoff, and log a warning when all three
lose instead of quietly polling a stale ref.

Surfaced by the two-slot backfill this guidance introduced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbZuWNDFy7kjXh9kLfA4dP
Copilot AI review requested due to automatic review settings August 25, 2026 00:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The PR description claims “docs-only” despite an executable script change, and the new fetch-retry logic should retain failure details in logs to keep diagnosis actionable.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

.claude/skills/babysit-pipeline/run_spec.sh:91

  • fetch_main suppresses all git fetch stderr (2>/dev/null), so when the retries fail you only get a generic warning with no clue whether it was a ref-lock collision vs. an auth/network problem. Logging the last error (or per-attempt errors) to LOG would make this diagnosable without spamming stdout.
    git -C "$REPO" fetch origin main --quiet 2>/dev/null && return 0
    sleep $(( i * 3 ))
  done
  echo "[warn] git fetch origin main failed 3x — origin/main may be stale this round" | tee -a "$LOG"
  return 1
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +80 to +84
# Two drivers polling the same checkout collide on `.git/refs/remotes/origin/main`
# ("cannot lock ref ... is at X but expected Y"). A lost fetch leaves origin/main
# stale, which makes meta_present understate progress — so retry, and say so in
# the log when all three attempts lose, rather than silently polling a stale ref.
fetch_main() {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, and my fault: the script commit came after I wrote the description. Title and body updated — the scope line now reads "prose plus one executable change" and there is a dedicated section for the run_spec.sh behaviour change with its own verification.

On the log detail: fetch_main now captures git stderr and prints it with the warning. A ref-lock collision and an auth or network failure call for different responses, so discarding the message threw away the one bit that distinguishes them. Exercised against a bad ref → last error: fatal: couldn't find remote ref ….

- `gh run list` has no per-spec filter; show the jq title filter instead
  of a sentence that reads like a flag exists.
- Keep git's stderr in fetch_main's warning: a ref-lock collision and an
  auth or network failure need different responses, and swallowing the
  message hides which one happened.
- "spec ids" → "spec IDs", matching the repo's Google-style usage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbZuWNDFy7kjXh9kLfA4dP
Copilot AI review requested due to automatic review settings August 25, 2026 01:00
@MarkusNeusinger MarkusNeusinger changed the title docs(babysit-pipeline): correct the backfill guidance against the finished run docs(babysit-pipeline): correct the backfill guidance, retry the driver's fetch Aug 25, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The updated “halt-on-cluster” bullet is currently phrased in a self-contradictory way (run-count threshold vs. “count pairs”), which could cause incorrect operational decisions during a backfill.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

.claude/skills/babysit-pipeline/SKILL.md:111

  • The halt-on-cluster bullet mixes a run-count threshold ("≥5 failed Generate runs") with the instruction "Count pairs, not runs", which is internally contradictory and easy to misapply during an outage. Reword the condition to make it explicit that the decision is driven by distinct failing (spec, library) pairs, with the run count as supporting evidence.
- **Halt the whole queue** only on a failure CLUSTER — ≥5 failed
  `Generate:` runs in minutes across **≥3 distinct (spec, library)
  pairs** = model daily quota exhausted; a fallback model via
  `-f model=` can finish leftovers. Count pairs, not runs: one
  genuinely impossible pair burns three runs on its own retries, so
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

The bullet kept a "≥5 failed runs" clause and then said "count pairs,
not runs" — contradictory, and the kind of contradiction that gets
resolved the wrong way during an actual outage. The condition is now
just the pair count, with the run count named as the thing that does
NOT decide it and the reason why.

Reported by the Copilot reviewer on #10660.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbZuWNDFy7kjXh9kLfA4dP
- **Halt the whole queue** only on a failure CLUSTER (≥5 failed
`Generate:` runs in minutes = model daily quota exhausted; a
fallback model via `-f model=` can finish leftovers).
- **Halt the whole queue** only on a failure CLUSTER: **≥3 distinct

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and worth fixing rather than explaining away — a bullet that says "≥5 runs" and "count pairs, not runs" in the same breath gets resolved the wrong way precisely when someone is reading it under pressure.

The condition is now just the pair count:

Halt the whole queue only on a failure CLUSTER: ≥3 distinct (spec, library) pairs failing within minutes of each other = model daily quota exhausted […] The threshold is pairs, full stop — the raw run count says nothing, because one impossible pair spends three runs on its own auto-retries, so two bad pairs already produce six failures with the pipeline entirely healthy (observed 2026-08-24).

The run count now appears only as the thing that does not decide it.

Copilot AI review requested due to automatic review settings August 26, 2026 06:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

fetch_main returns non-zero but is called unguarded (can become fatal under bash -e/inherited set -e), and there’s a newly introduced “spec id” casing inconsistency in SKILL.md.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

.claude/skills/babysit-pipeline/run_spec.sh:97

  • fetch_main returns non-zero after logging, but it is invoked as a bare command. If the script is ever executed with -e enabled (e.g., bash -e run_spec.sh or set -e inherited from a parent shell), this will abort the whole driver on a transient ref-lock collision—the opposite of the intended “warn and keep polling stale origin/main for this round” behavior.

This issue also appears on line 126 of the same file.

fetch_main

.claude/skills/babysit-pipeline/run_spec.sh:126

  • Same as above: calling fetch_main unguarded means a non-zero return can terminate the loop early when -e is in effect. If the goal is to keep polling even when the fetch lost 3x, make this call non-fatal.
  fetch_main

.claude/skills/babysit-pipeline/SKILL.md:223

  • Use the conventional uppercase acronym “ID” in this heading sentence for consistency with the surrounding text (and with earlier corrections): “A spec ID from an issue title may not exist.”
- **A spec id from an issue title may not exist.** `impl:*:failed`
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@MarkusNeusinger
MarkusNeusinger merged commit b1d9446 into main Aug 26, 2026
10 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the docs/babysit-skill-corrections branch August 26, 2026 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants